package taliav3;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.io.*;
import java.net.*;

/**
 *
 *
 * W klasie tej rysowany jest stol, karty.
 * Zakladany jest serwer/polaczenie klient->serwer.
 * Dodawane sa zdarzenia.
 *
 */

public class DrawTable extends Thread{
    protected static Point point = new Point();
    protected boolean end=false;
    ServerSocket SerwerowySocet;
    Socket polaczenie = null;
    Socket requestSocket;
    ObjectInputStream wejscie;
    static ObjectOutputStream wyjscie;
    boolean Server=false;
    JFrame table;
    JLayeredPane panel;
    Dealer talia;
    Card activeC;
    JLabel menu[],colors[],ranks[],sort[],BG,bgDC,bgDR,peek,punishL,exit,titlebar,minimize,status;
    /** Player object type array to store player cards*/
    Player players[];
    /** Arraylist which stores Card objects which user has selected to throw.*/
    ArrayList <Card> Selected;
    int ind, BackUpDemandQueue, taliaI, rewersI, joker, player,port;
    boolean peeked,peeked_B,jokers,walet,as,black,koniec_gry;
    char BackUpDemand;
    String path, serwerpath;
    Color color;
    private long waitTime=60;
    /**
     * Constructor which sets table accoring to parameters. This one creates background with specified image.
     * @param get
     * @param path
     * @param black
     * @param taliaI
     * @param rewersI
     * @param joker
     * @param Server
     * @param serwerPath
     * @param port
     */
    public DrawTable(int get, String path, boolean black, int taliaI, int rewersI, int joker, boolean Server, String serwerPath, int port)
    {
        this.port=port;
        this.player=get;
        this.path = path;
        this.black = black;
        this.rewersI = rewersI;
        this.taliaI = taliaI;
        this.Server = Server;
        this.joker = joker;
        this.serwerpath= serwerPath;
        GenericDraw(get);
        SetBg(path);
        table.setVisible(true);
        panel.remove(BG);
        panel.add(BG);
        status.setOpaque(true);
    }
    /**
     * Constructor which sets table accoring to parameters. This one creates background with solid color.
     * @param get
     * @param color
     * @param black
     * @param taliaI
     * @param rewersI
     * @param joker
     * @param Server
     * @param serwerPath
     * @param port
     */
    public DrawTable(int get, Color color, boolean black, int taliaI, int rewersI, int joker, boolean Server, String serwerPath, int port)
    {
        this.player=get;
        this.color = color;
        this.black = black;
        this.rewersI = rewersI;
        this.taliaI = taliaI;
        this.Server = Server;
        this.joker = joker;
        GenericDraw(get);
        SetBg(color);
        table.setVisible(true);
    }
    private void GenericDraw(int get)
    {
	koniec_gry=false;
        status = new JLabel();
        exit = new JLabel();
        minimize = new JLabel();
        titlebar = new JLabel();
        players = new Player[get];
        table = new JFrame();
        peek = new JLabel();
        Selected = new ArrayList<Card>();
        menu = new JLabel[5];
        BG = new JLabel();
        panel = new JLayeredPane();
        talia = new Dealer(1,joker,taliaI);
        talia.rewers = "/taliav3/img/Rewersy/rewers";
        talia.rewers +=rewersI+".png";
        colors = new JLabel[4];
        sort = new JLabel[4];
        bgDC = new JLabel();
        bgDR = new JLabel();
        Labels.setLabel(exit, 1112, 2, 30, 17, "/taliav3/img/close.png", MouseAdapters.closeFrame());
        Labels.setLabel(minimize, 1083, 2, 29, 17, "/taliav3/img/min.png", MouseAdapters.minimizeFrame(table));
        Labels.setLabel(titlebar, 0, 0, 1143, 21, "/taliav3/img/titlebar.png",MouseAdapters.getFrameLocation(this),MouseAdapters.moveFrame(this));
        table.setUndecorated(true);
        BackUpDemand='0';
        BackUpDemandQueue=0;
        peeked = false;
        peeked_B = false;
        panel.setLayout(null);
        table.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        for(int i=0; i<get; i++)
        {
            players[i] = new Player();
            talia.GiveOutDeck(players[i], get, i+1, 6);
            players[i].X_width = 500;
        }
        players[0].Y_height = 448;
        players[1].Y_height = 45;
        int X=500;
        int Y=450;
        talia.Begin();
        Card b = new Card();
        if(Server==false)
        {
            long time=Calendar.getInstance().get(Calendar.SECOND);
            if(time<waitTime)
                time+=Math.abs(waitTime-time);
            while(Calendar.getInstance().get(Calendar.SECOND)-time<waitTime)
            try
            {
                requestSocket = new Socket(serwerpath, port);
               
                System.out.println("Connected to localhost in port 2004");
                wejscie = new ObjectInputStream(requestSocket.getInputStream());
                wyjscie = new ObjectOutputStream(requestSocket.getOutputStream());
                try
                {
                    b = (Card)wejscie.readObject();
                    talia.ActiveCard = b;
                    talia.ActiveCard.pathAwers=Card.ImagePath(talia.ActiveCard.color, talia.ActiveCard.rank, taliaI);
                    break;
                }
                catch(ClassNotFoundException classnot)
                {
                    System.err.println("Data received in unknown format");
                }
            }
            catch(ConnectException conException)
            {
                conException.printStackTrace();
            }
            catch(IOException ioException){
                ioException.printStackTrace();              
            }
            if(wejscie==null || wyjscie==null)
            {
                new MainMenu("Nie nawiązano połączenia w czasie.",rewersI,taliaI,joker,path,Server,port,serwerpath);
            }
        }
        else
        {
            try
            {
                SerwerowySocet = new ServerSocket(port);
                SerwerowySocet.setSoTimeout((int)(waitTime*1000));
                System.out.println("Waiting for polaczenie");
                polaczenie = SerwerowySocet.accept();

                wyjscie = new ObjectOutputStream(polaczenie.getOutputStream());
                wyjscie.flush();
                wejscie = new ObjectInputStream(polaczenie.getInputStream());
            }
            catch(SocketTimeoutException stException){
                new MainMenu("Czas oczekiwania zakończony",rewersI,taliaI,joker,path,Server,port,serwerpath);
                try {
                    SerwerowySocet.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            catch(BindException bException)
            {
                new MainMenu("Zablokowane łącze. Sprawdź czy port nie jest zablokowany.",rewersI,taliaI,joker,path,Server,port,serwerpath);
            }
            catch(IOException ioException)
            {
                ioException.printStackTrace();
            }
            
        }
        System.out.println(wejscie);
        System.out.println(wyjscie);
        if(wejscie!= null || wyjscie!=null){
            int height=150;
            if(taliaI!=1)
                height=186;

            int p_index=0, s_index=0;
            boolean hide=false;
            if(Server==true)
            {
                p_index=0;
                s_index=1;
            }
            else
            {
                p_index=1;
                s_index=0;
            }
            DrawCards(p_index, hide, 0, X, players[0].Y_height, 120, height,false);
            DrawCards(s_index, !hide, 0, X, players[1].Y_height, 120, height,true);
            activeC = talia.ActiveCard;
            Labels.setLabel(activeC, 450, (players[0].Y_height+30)/2, 120, 186, talia.ActiveCard.pathAwers);
            if(Server==true)
                players[0].active=true;
            else
                players[1].active=true;
            menu();
            panel.add(activeC);
            panel.add(exit);
            panel.add(minimize);
            panel.add(titlebar);
            panel.add(bgDC);
            panel.add(bgDR);
            for(int i=0; i<4; i++)
            {
                colors[i] = new JLabel();
                sort[i] = new JLabel();
                panel.add(colors[i]);
                panel.add(sort[i]);
            }
            ranks = new JLabel[13];
            for(int i=0; i<13; i++)
            {
                ranks[i] = new JLabel();
                panel.add(ranks[i]);
            }
            panel.add(BG);
            table.add(panel);
            table.setSize(1143,700);
            table.setLocationRelativeTo(null);
            if(Server==false)
            {
                NetworkAdapters.OdbiorClient(this);
                MouseAdapters.blockContent(this,1);
            }
            else
            {
                NetworkAdapters.WyjscieServer(this);
                MouseAdapters.unlockContent(this);                                
            }
            start();
        }
    }
    public void run()
    {
        while(koniec_gry==false)
        {            
            NetworkAdapters.Read(this, this);
            ReDrawComponents(true,0);
            if(koniec_gry==true)
                endgame();
            panel.remove(BG);
            panel.add(BG);
            status.setOpaque(true);
        }
    }
    /**
     * Method draws cards accoring to parameter hide (when true, no action listeners are added to cards).
     * @param p_index
     * @param hide
     * @param start_index
     * @param X
     * @param Y
     * @param width
     * @param height
     * @param block
     */
    private void DrawCards(int p_index, boolean hide, int start_index, int X, int Y, int width, int height, boolean block)
    {
        int BackX = X;
        for(int i=start_index; i<players[p_index].tPlayer.size(); i++, X-=20)
        {
            if(hide==false)
                players[p_index].getCard(i).setIcon(new ImageIcon(getClass().getResource(players[p_index].getCard(i).pathAwers)));
            else
                players[p_index].getCard(i).setIcon(new ImageIcon(getClass().getResource(talia.rewers)));
            panel.moveToFront(players[p_index].getCard(i));
            players[p_index].getCard(i).setBounds(X, Y, width, height);
            if(players[p_index].getCard(i).getMouseListeners().length>0)
                for(int j=players[p_index].getCard(i).getMouseListeners().length-1; j>=0; j--)
                    players[p_index].getCard(i).removeMouseListener(players[p_index].getCard(i).getMouseListeners()[j]);
            if(hide==false && block==false)
                players[p_index].getCard(i).addMouseListener(MouseAdapters.pickCardAction(this, p_index));
            panel.add(players[p_index].getCard(i));
        }
    }
    /** Method which helps determine what card has been clicked*/
    protected int GetIndex(int p_index, int X, int defX)
    {
        int Index = 0, backX=defX;
        for(; Index<players[p_index].tPlayer.size(); Index++, backX-=20)
            if(X==backX)
                return Index;
        return -1;
    }
    /** Method which sets background with image.*/
    private void SetBg(String path)
    {
        BG.setOpaque(true);
        Labels.setLabel(BG, 0, 0, 1143, 700, path);
    }
    /** Method which sets background with solid color.*/
    private void SetBg(Color c)
    {
        BG.setOpaque(true);
        BG.setBackground(c);
        BG.setBounds(0, 0, 1143, 700);
    }
    /** Method which redraw the whole table*/
    protected void ReDrawComponents(boolean hide, int minus)
    {
        int p_index=0,s_index=0;
        if(Server==true)
        {
            p_index=0;
            s_index=1;
        }
        else
        {
            p_index=1;
            s_index=0;
        }
        Selected.removeAll(Selected);
        panel.removeAll();
        if(players[p_index].tPlayer.size()>6)
        {
            int X=Math.abs(6-players[p_index].tPlayer.size())*10;
            players[p_index].X_width=500+X;
        }
        if(players[s_index].tPlayer.size()>6)
        {
            int X=Math.abs(6-players[s_index].tPlayer.size())*10;
            players[s_index].X_width=500+X;
        }
        int height=150;
        if(taliaI!=1)
            height=186;
        DrawCards(p_index,!hide,0,players[p_index].X_width,players[0].Y_height,120,height,false);
        DrawCards(s_index,hide,0,players[s_index].X_width,players[1].Y_height,120,height,true);
        activeC.setIcon(new ImageIcon(getClass().getResource(talia.ActiveCard.pathAwers)));
        panel.add(activeC);
        menu();
        if(talia.get!=0 || players[0].QueueStop>0 || players[1].QueueStop>0 || talia.demand!='0' || talia.ActiveCard.joker)
            punish(minus);
        panel.add(exit);
        panel.add(minimize);
        panel.add(titlebar);
        panel.add(status);
        status.setBounds(2, 700-52, 600, 50);
        status.setOpaque(true);
        status.setBackground(Color.green);
        status.setForeground(Color.black);
        Font font1 = new Font("Century Gothic", Font.PLAIN, 30);
        status.setFont(font1);
        status.setText("  Twoj ruch");        
        panel.add(BG);
        
        if(koniec_gry==true)
            endgame();             
    }
    /** Method draws extra information about punish (figure/rank demand, cards to take).*/
    private void punish(int minus)
    {
        JLabel text = new JLabel();
        punishL = new JLabel();
        Font font1 = new Font("Century Gothic", Font.BOLD, 30);
        text.setFont(font1);
        text.setBounds(600, 350, 225, 40);
        punishL.setFont(font1);
        String pun="";
        if(talia.get>=1)
        {
            text.setText("Do pobrania...");
            if(minus==1)
                pun+="+"+(talia.get-1)+" ";
            else
                pun+="+"+talia.get+" ";
            if(talia.get==2 || talia.get==22 || talia.get==32 || talia.get==42 || talia.get==52 ||
               talia.get==3 || talia.get==23 || talia.get==33 || talia.get==43 || talia.get==53 ||
               talia.get==4 || talia.get==24 || talia.get==34 || talia.get==44 || talia.get==54)
                pun+="karty";
            else if(talia.get==1)
                pun+="karta";
            else
                pun+="kart";
        }
        else if( (players[0].QueueStop>0 && players[0].active==true) || (players[1].QueueStop>0 && players[1].active==true) )
        {
            if(players[0].active==true)
            {
                text.setText("Czekasz...");
                if(players[0].QueueStop>talia.players && players[0].QueueStop<5*talia.players)
                    pun+=(players[0].QueueStop/talia.players)+" kolejki";
                else if(players[0].QueueStop>=5*talia.players)
                    pun+=(players[0].QueueStop/talia.players)+" kolejek";
                else
                    pun+="kolejkę";
            }
            else
            {
                text.setText("Czekasz...");
                if(players[1].QueueStop>talia.players && players[1].QueueStop<5*talia.players)
                    pun+=(players[1].QueueStop/talia.players)+" kolejki";
                else if(players[1].QueueStop>=5*talia.players)
                    pun+=(players[1].QueueStop/talia.players)+" kolejek";
                else
                    pun+="kolejkę";
            }
        }
        else if(talia.demand!='0')
        {
            text.setText("Żądanie...");
            if(talia.demand=='H' || talia.demand=='S' || talia.demand=='C' || talia.demand=='D')
            {
                char colors[]={'H','S','C','D'};
                for(int i=0; i<colors.length; i++)
                    if(talia.demand==colors[i])
                        punishL.setIcon(new ImageIcon(getClass().getResource("/taliav3/img/"+colors[i]+"m.png")));
            }
            else
            {
                if(talia.demand!='Q')
                    pun+=""+talia.demand;
                else if(talia.demand=='Q')
                    pun+="Dama";
                if(talia.demand=='1')
                    pun+="0";
            }
        }
        else if(talia.getActiveCard().joker==true)
        {
            text.setText("Na stole: ");
            char colors[]={'H','S','C','D'};
            for(int i=0; i<colors.length; i++)
                if(talia.getActiveCard().color==colors[i])
                    punishL.setIcon(new ImageIcon(getClass().getResource("/taliav3/img/"+colors[i]+"m.png")));
            if(talia.getActiveCard().rank=='Q' || talia.getActiveCard().rank=='J' 
                    || talia.getActiveCard().rank=='A' || talia.getActiveCard().rank=='K')
            {
                if(talia.getActiveCard().rank=='Q')
                    pun = "Dama";
                else if(talia.getActiveCard().rank=='J')
                    pun = "Walet";
                if(talia.getActiveCard().rank=='A')
                    pun = "As";
                else
                    pun = "Król";
            }
            else
                pun += talia.getActiveCard().rank;
        }
        punishL.setText(pun);
        if(black)   {  text.setForeground(Color.black); punishL.setForeground(Color.black); }
        else    {   text.setForeground(Color.white);    punishL.setForeground(Color.white); }
        punishL.setBounds(690, 390, 180, 40);
        panel.add(text);
        panel.add(punishL);
    }
    /** Method draws menubar on to bottom of the screen.*/
    private void menu()
    {
        for(int i=0; i<5; i++)
            menu[i] = new JLabel();
        Labels.setLabel(menu[0], 425, 646, 79, 52, "/taliav3/img/menu1.png");
        int x = 500;
        int sizes[] = {171,208,121,140};
        String paths[] = {"rzuc", "pobierz", "sortuj", "blank"};
        if(( (players[0].QueueStop>0 || players[0].stop==true) && Server==true) || ((players[1].QueueStop>0 || players[1].stop==true) && Server==false))
            paths[1]="czekaj";
        Labels.setLabel(menu[1], x, 646, sizes[0], 52, ("/taliav3/img/menu_"+paths[0]+".png"), MouseAdapters.pickMenuAction(path,this));
        x+=menu[1].getWidth();
        for(int index=2; index<5; index++)
        {
            final String path="/taliav3/img/menu_"+paths[index-1];
            Labels.setLabel(menu[index], x, 646, sizes[index-1], 52, (path+"Dis.png"), MouseAdapters.pickMenuAction(path,this));
            x+=menu[index].getWidth();
        }
        for(int i=0; i<5; i++)
            panel.add(menu[i]);
    }
    /** This method is used to give player a choice to throw just added card from the deck.*/
    protected void peekframe(Player player, int punish, boolean which)
    {
        int peekedI = player.tPlayer.size()-1;
        player.tPlayer.get(peekedI).ind=peekedI;
        if(player.MovePossible(player.tPlayer.size()-1, talia))
        {
            peeked=true;
            if(Server!=true)
                which=!which;
            ReDrawComponents(which,1);
            player.tPlayer.get(peekedI).setLocation(player.tPlayer.get(peekedI).getX(),
            player.tPlayer.get(peekedI).getY()-40);
            if(player.tPlayer.get(peekedI).getMouseListeners().length>0)
                player.tPlayer.get(peekedI).removeMouseListener(player.tPlayer.get(peekedI).getMouseListeners()[0]);
            player.tPlayer.get(peekedI).addMouseListener(MouseAdapters.pickPeeked(this));
            Selected.add(new Card(player.tPlayer.get(peekedI)));
            if( player.tPlayer.get(peekedI).rank=='B')
                menu[4].setIcon(new ImageIcon(getClass().getResource("/taliav3/img/menu_jokerWyb.png")));
            else if( player.tPlayer.get(peekedI).rank=='A' || player.tPlayer.get(peekedI).rank=='J')
                menu[4].setIcon(new ImageIcon(getClass().getResource("/taliav3/img/menu_demandWyb.png")));
            if(player.tPlayer.get(peekedI).rank=='J')
                walet=true;
            else if(player.tPlayer.get(peekedI).rank=='A')
                as=true;
            else if(player.tPlayer.get(peekedI).rank=='B')
                jokers=true;
            MouseAdapters.menu_special(player.tPlayer.get(peekedI).rank,this);
            menu[2].setIcon(new ImageIcon(getClass().getResource("/taliav3/img/menu_pobierzDis.png")));
            menu[3].setIcon(new ImageIcon(getClass().getResource("/taliav3/img/menu_sortujDis.png")));
            if(player.tPlayer.get(peekedI).rank!='B')
                menu[1].setIcon(new ImageIcon(getClass().getResource("/taliav3/img/menu_rzucDis.png")));
            panel.remove(BG);
            panel.add(BG);
            status.setOpaque(true);

            MouseAdapters.blockContent(this,2);
        }
        else
        {
            if(punish>0 && talia.Decks.size()>punish)
                player.getCards(talia, (talia.get-1));
            else if(punish>0 && talia.Decks.size()<punish)
                player.getCards(talia, talia.Decks.size()-1);
            talia.get=0;
            peeked=false;
            peeked_B=false;
            ReDrawComponents(true,0);
            panel.remove(BG);
            panel.add(BG);
            status.setOpaque(true);
            MouseAdapters.blockContent(this,1);
            NetworkAdapters.Write(this);
        }
    }
    /** Drawing end of game.*/
    protected void endgame()
    {
        panel.removeAll();
        BG.setIcon(new ImageIcon(getClass().getResource("/taliav3/img/stol_end.jpg")));
        JLabel labelik= new JLabel() ;
        labelik.setBounds(780, 600, 320, 92);
        if ( (players[0].tPlayer.size()==0 && Server==true) ||  (players[1].tPlayer.size()==0 && Server==false))
            labelik.setIcon(new ImageIcon(getClass().getResource("/taliav3/img/winner.png")));
        else
            labelik.setIcon(new ImageIcon(getClass().getResource("/taliav3/img/looser.png")));
        BG.addMouseListener(MouseAdapters.NewGame(this));
        panel.add(labelik);
        panel.add(minimize);
        panel.add(exit);
        panel.moveToFront(minimize);
        panel.moveToFront(exit);
        panel.add(titlebar);
        panel.add(BG);
        table.add(panel);
        panel.repaint();
    }
}